package net.stock.controller;

import net.stock.domain.ItemPrice;
import net.stock.service.StockDao;
import net.stock.service.StockService;
import net.stock.utils.StockUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author naim
 * @date Dec 23, 2009
 */
@Controller(value = "/cron")
public class CronInvoker {
    private Logger log = Logger.getLogger(getClass().getName());

    private boolean enableAutomaticNotifications = true;

    @Autowired
    private StockService stockService;

    @Autowired
    private StockDao stockDao;

    @RequestMapping(method = RequestMethod.GET, value = "/monitor")
    public void monitor(HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.log(Level.INFO, "Monitoring Application: Keeping it alive");
        StockUtils.writeToResponseOutputStream(response, "Monitoring Application: Keeping it alive");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/downloadLatestPrice")
    public ModelAndView downloadLatestPrice(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        boolean bypass = ServletRequestUtils.getBooleanParameter(request, "bypass", false);

        if (!bypass && !isWorkingHour()) {
            StockUtils.writeToResponseOutputStream(response, "Not working hour! Skipping from downloading latest price.");
            return null;
        }

        boolean downloadSuccessful = stockService.downloadLatestPrice();

        if (downloadSuccessful) {
            Map<String, Float> priceMap = stockService.getLatestPriceMap();
            if (priceMap.size() > 0) {

                if (enableAutomaticNotifications) {
                    notifyUsers(priceMap);
                }

                DateTime dt = new DateTime(StockUtils.timeZone);
                log.log(Level.INFO, "Will delete previously saved day prices now.");
                stockDao.deletePrices(dt);

                log.log(Level.INFO, "Will save the new day prices now. items: " + priceMap.size());
                stockDao.saveDayPrices(dt, priceMap);
            }
        }

        String body = "Cron for downloading latestPrice has returned, download successful: " + downloadSuccessful;
        log.log(Level.INFO, body);
        StockUtils.writeToResponseOutputStream(response, body);
        return null;
    }

    private void notifyUsers(Map<String, Float> priceMap) {
        log.log(Level.INFO, "Sending Automatic Notifications");

        Map<String, List<ItemPrice>> userNotifMap = stockDao.getNotifMapForAllUsers(priceMap);
        for (String email : userNotifMap.keySet()) {
            log.log(Level.INFO, "Sending Automatic Notifications to " + email);
            stockService.sendNoifications(email, userNotifMap.get(email));
        }
    }

    @RequestMapping(method = RequestMethod.GET, value = "/notify")
    public ModelAndView notify(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (enableAutomaticNotifications && isWorkingHour()) {
            notifyUsers(stockService.getLatestPriceMap());
            StockUtils.writeToResponseOutputStream(response, "Notifications sent!");
        } else {
            StockUtils.writeToResponseOutputStream(response, "Either 'Automatic Notification' feature is disabled or Not working hour!.");
        }
        return null;
    }


    @RequestMapping(method = RequestMethod.GET, value = "/enable")
    public ModelAndView enableAutoNotifications(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        enableAutomaticNotifications = true;
        StockUtils.writeToResponseOutputStream(response, "Automatic Notifications are Enabled");
        return null;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/disable")
    public ModelAndView disableAutoNotifications(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        enableAutomaticNotifications = false;
        StockUtils.writeToResponseOutputStream(response, "Automatic Notifications are Disabled");
        return null;
    }

    private boolean isWorkingHour() {
        DateTime dateTime = new DateTime(StockUtils.timeZone);
        int hourOfDay = dateTime.getHourOfDay();
        return hourOfDay > 9 && hourOfDay < 18;
    }

}
